#include "loger.h"

string getTimeDate()
{
    time_t timep;
    time (&timep);
    char tmp[64];
    strftime(tmp, sizeof(tmp), "%Y-%m-%d",localtime(&timep) );
    return string(tmp);
}

string getTime()
{
    time_t timep;
    time (&timep);
    char tmp[64];
    strftime(tmp, sizeof(tmp), "%Y-%m-%d %H:%M:%S",localtime(&timep) );
    return string(tmp);
}

void Loger::SetMinimalLevel(Level level){
    mLevel = level;
}

int Loger::Debug(string dat,string  function,int line) {
    if(mLevel  > LEVEL_DEBUG) {     
        return 0;
    }    
    std::lock_guard<std::mutex> guard(mMux);
    if (!mValid){
        this->mCurrentDate = getTimeDate();
        this->mCurrentPath = this->mPath + "/" + this->mPrefix + "/" +  this->mCurrentDate + ".log";
        this->mFile = fopen(mCurrentPath.c_str(),"w+");
        if (this->mFile == nullptr){
            mValid = false;
            std::cout<<"error Loger open file\r\n"<<std::endl;
            return -1;
        }
    }
        // 还没有过天
    if(getTimeDate() == this->mCurrentDate){
        string tmp = "[DEBUG] ";
        tmp += getTime();
        tmp += ": ";
        tmp += dat;
        tmp += "  at    [" + function + " line " + std::to_string(line) + "]";
        tmp += "\n";
        int ret =fwrite(tmp.c_str(),tmp.size(),1,this->mFile);
        fflush(this->mFile);
        return ret;
    }else{    // 已经过天了
        this->mCurrentDate = getTimeDate();
        string path = getTimeDate() + ".log";
        this->mFile = fopen(path.c_str(),"w+");
        if (this->mFile == nullptr){
            mValid = false;
            std::cout<<"error Loger open file\r\n"<<std::endl;
            return -1;            
        }
        string tmp = "[DEBUG] ";
        tmp += getTime();
        tmp += ": ";
        tmp += dat;
        tmp += "at    [" + function + " line " + std::to_string(line) + "]";
        tmp += "\n";
        int ret = fwrite(tmp.c_str(),tmp.size(),1,this->mFile);
        fflush(this->mFile);
        return ret;
    }
    return 0;
}


int Loger::Error(string dat,string  function,int line) {
    std::lock_guard<std::mutex> guard(mMux);
    if (!mValid){
        this->mCurrentDate = getTimeDate();
        this->mCurrentPath = this->mPath + "/" + this->mPrefix + "/" +  this->mCurrentDate + ".log";
        this->mFile = fopen(mCurrentPath.c_str(),"w+");
        if (this->mFile == nullptr){
            mValid = false;
            std::cout<<"error Loger open file\r\n"<<std::endl;
            return -1;
        }
    }
        // 还没有过天
    if(getTimeDate() == this->mCurrentDate){
        string tmp = "[ERROR] ";
        tmp += getTime();
        tmp += ": ";
        tmp += dat;
        tmp += "  at    [" + function + " line " + std::to_string(line) + "]";
        tmp += "\n";
        int ret =fwrite(tmp.c_str(),tmp.size(),1,this->mFile);
        fflush(this->mFile);
        return ret;
    }else{    // 已经过天了
        this->mCurrentDate = getTimeDate();
        string path = getTimeDate() + ".log";
        this->mFile = fopen(path.c_str(),"w+");
        if (this->mFile == nullptr){
            mValid = false;
            std::cout<<"error Loger open file\r\n"<<std::endl;
            return -1;            
        }
        string tmp = "[ERROR] ";
        tmp += getTime();
        tmp += ": ";
        tmp += dat;
        tmp += "at    [" + function + " line " + std::to_string(line) + "]";
        tmp += "\n";
        int ret = fwrite(tmp.c_str(),tmp.size(),1,this->mFile);
        fflush(this->mFile);
        return ret;
    }
    return 0;
}


int Loger::Warning(string dat,string  function,int line) {
    if(mLevel  >  LEVEL_WARNING) {
        return 0;
    }
    std::lock_guard<std::mutex> guard(mMux);
    if (!mValid){
        this->mCurrentDate = getTimeDate();
        this->mCurrentPath = this->mPath + "/" + this->mPrefix + "/" +  this->mCurrentDate + ".log";
        this->mFile = fopen(mCurrentPath.c_str(),"w+");
        if (this->mFile == nullptr){
            mValid = false;
            std::cout<<"error Loger open file\r\n"<<std::endl;
            return -1;
        }
    }
        // 还没有过天
    if(getTimeDate() == this->mCurrentDate){
        string tmp = "[WARNING] ";
        tmp += getTime();
        tmp += ": ";
        tmp += dat;
        tmp += "  at    [" + function + " line " + std::to_string(line) + "]";
        tmp += "\n";
        int ret =fwrite(tmp.c_str(),tmp.size(),1,this->mFile);
        fflush(this->mFile);
        return ret;
    }else{    // 已经过天了
        this->mCurrentDate = getTimeDate();
        string path = getTimeDate() + ".log";
        this->mFile = fopen(path.c_str(),"w+");
        if (this->mFile == nullptr){
            mValid = false;
            std::cout<<"error Loger open file\r\n"<<std::endl;
            return -1;            
        }
        string tmp = "[WARNING] ";
        tmp += getTime();
        tmp += ": ";
        tmp += dat;
        tmp += "at    [" + function + " line " + std::to_string(line) + "]";
        tmp += "\n";
        int ret = fwrite(tmp.c_str(),tmp.size(),1,this->mFile);
        fflush(this->mFile);
        return ret;
    }
    return 0;
}

int Loger::Info(string dat,string  function,int line) {
    if(mLevel  >  LEVEL_WARNING){
        return 0;
    }    
    std::lock_guard<std::mutex> guard(mMux);
    if (!mValid){
        this->mCurrentDate = getTimeDate();
        this->mCurrentPath = this->mPath + "/" + this->mPrefix + "/" +  this->mCurrentDate + ".log";
        this->mFile = fopen(mCurrentPath.c_str(),"w+");
        if (this->mFile == nullptr){
            mValid = false;
            std::cout<<"error Loger open file\r\n"<<std::endl;
            return -1;
        }
    }
        // 还没有过天
    if(getTimeDate() == this->mCurrentDate){
        string tmp = "[INFO] ";
        tmp += getTime();
        tmp += ": ";
        tmp += dat;
        tmp += "  at    [" + function + " line " + std::to_string(line) + "]";
        tmp += "\n";
        int ret =fwrite(tmp.c_str(),tmp.size(),1,this->mFile);
        fflush(this->mFile);
        return ret;
    }else{    // 已经过天了
        this->mCurrentDate = getTimeDate();
        string path = getTimeDate() + ".log";
        this->mFile = fopen(path.c_str(),"w+");
        if (this->mFile == nullptr){
            mValid = false;
            std::cout<<"error Loger open file\r\n"<<std::endl;
            return -1;            
        }
        string tmp = "[INFO] ";
        tmp += getTime();
        tmp += ": ";
        tmp += dat;
        tmp += "at    [" + function + " line " + std::to_string(line) + "]";
        tmp += "\n";
        int ret = fwrite(tmp.c_str(),tmp.size(),1,this->mFile);
        fflush(this->mFile);
        return ret;
    }
    return 0;
}


void Loger::operator+(const string& wb){
    std::lock_guard<std::mutex> guard(mMux);
    if (!mValid){
        this->mCurrentDate = getTimeDate();
        this->mCurrentPath = this->mPath + "/" + this->mPrefix + "/" +  this->mCurrentDate + ".log";
        this->mFile = fopen(mCurrentPath.c_str(),"w+");
        if (this->mFile == nullptr){
            mValid = false;
            std::cout<<"error Loger open file\r\n"<<std::endl;
            return ;
        }
    }
    // 还没有过天
    if(getTimeDate() == this->mCurrentDate) {
        string tmp = "[" + this->mPrefix + "] ";
        tmp += getTime();
        tmp += ":";
        tmp += wb;
        tmp += " \n";
        fwrite(tmp.c_str(),tmp.size(),1,this->mFile);
        fflush(this->mFile);
    } else {    // 已经过天了
        this->mCurrentDate = getTimeDate();
        string path = getTimeDate() + ".log";
        this->mFile = fopen(path.c_str(),"w+");
        if (this->mFile == nullptr){
            mValid = false;
            std::cout<<"error Loger open file\r\n"<<std::endl;
            return ;            
        }
        string tmp = "[" + this->mPrefix + "] ";
        tmp += getTime();
        tmp += ":";
        tmp += wb;
        tmp += " \n";
        fwrite(tmp.c_str(),tmp.size(),1,this->mFile);
        fflush(this->mFile);
    }
}

void Loger::operator<<(const string& wb){
    std::lock_guard<std::mutex> guard(mMux);
    if (!mValid){
        this->mCurrentDate = getTimeDate();
        this->mCurrentPath = this->mPath + "/" + this->mPrefix + "/" +  this->mCurrentDate + ".log";
        this->mFile = fopen(mCurrentPath.c_str(),"w+");
        if (this->mFile == nullptr){
            mValid = false;
            std::cout<<"error Loger open file\r\n"<<std::endl;
            return ;
        }
    }
    if(getTimeDate() == this->mCurrentDate){
        string tmp = "[" + this->mPrefix + "] ";
        tmp += getTime();
        tmp += ":";
        tmp += wb;
        tmp += " \n";
        fwrite(tmp.c_str(),tmp.size(),1,this->mFile);
        fflush(this->mFile);
    }else{    // 已经过天了
        this->mCurrentDate = getTimeDate();
        this->mCurrentPath = this->mPath + "/" + this->mPrefix + "/" +  this->mCurrentDate + ".log";
        this->mFile = fopen(mCurrentPath.c_str(),"w+");
        if (this->mFile == nullptr){
            mValid = false;
            std::cout<<"error Loger open file\r\n"<<std::endl;
            return ;            
        }
        string tmp = "[" + this->mPrefix + "] ";
        tmp += getTime();
        tmp += ":";
        tmp += wb;
        tmp += " \n";
        fwrite(tmp.c_str(),tmp.size(),1,this->mFile);
        fflush(this->mFile);
    }
}

bool file_existed(string path)  {
    fstream _file;
    _file.open(path.c_str(),ios::in);
    if(!_file)
    {
        return false;
    }
    else
    {
        _file.close();
        return true;
    }
}

Loger::~Loger(){
    if(mValid){
        fflush(mFile);
        fclose(mFile);
    }
}

Loger::Loger(string path,string prefix)  {
    mLevel = LEVEL_INFO;
    this->mPath  = path;
    this->mPrefix = prefix;
    this->mCurrentDate = getTimeDate();
    this->mCurrentPath = path + "/" + prefix + "-" +  this->mCurrentDate + ".log";
    mValid = false;

    this->mFile = fopen(this->mCurrentPath.c_str(),"a+");
    if(! this->mFile){
        fprintf(stderr,"error open log files %s code %d,please check file path",this->mCurrentPath.c_str(),errno);
        exit(0);
    }else{
        mValid = true;
    }
}

Loger::Loger(string path,string prefix,bool old)  {
    mLevel = LEVEL_INFO;
    this->mPath  = path;
    this->mPrefix = prefix;
    this->mCurrentDate = getTimeDate();
    this->mCurrentPath = path + "/" + prefix + "-" +  this->mCurrentDate + ".log";
    mValid = false;

    if(old){
        this->mFile = fopen(this->mCurrentPath.c_str(),"w+");
    }else{
        this->mFile = fopen(this->mCurrentPath.c_str(),"a+");
    }
    if(!this->mFile){
        fprintf(stderr,"error open log files %s code %d,please check file path",this->mCurrentPath.c_str(),errno);
        exit(0);
    }else{
        mValid = true;
    }
}

int Loger::DumpOBJ(void *dst,int rowNum,int num,bool ifAsii,char *out){
    // char out [2048];
    int row = num / rowNum;
    int left = num %rowNum;
    if (left != 0){
        row += 1;
    }
    snprintf(out,5,"LN: ");
    for (int z = 1;z < rowNum + 1; z++) {
        char tmp[6] = {0};
        sprintf(tmp,"%02d ",z);
        strcat(out,tmp);
    }
    strcat(out," ");

    if (ifAsii) {
        for (int z = 1;z < rowNum + 1; z++) {
            char tmp[6] = {0};
            sprintf(tmp,"%02d ",z);
            strcat(out,tmp);
        }
    }
    strcat(out,"\r\n");
    for(int i = 0;i < row;i ++) {
        string rowstr;
        char tmp[6] = {0};
        sprintf(tmp,"%02x",i + 1);
        rowstr += string(tmp) + ": ";
        //last row
        if (i == row -1 && left != 0){
            for (int z = 0;z < rowNum; z++) {
                char tmp[6] = {0};
                if (z < left){
                    sprintf(tmp,"%02x",((unsigned char)(((unsigned char *)dst)[ z + i * rowNum])));
                }else{
                    sprintf(tmp,"  ");
                }
                rowstr += string(tmp) + " ";
                if (z == left - 1) {
                    if (!ifAsii)
                        rowstr += "\r\n";
                }
            }
            rowstr += " ";
            if(ifAsii) {
                for (int z = 0;z < left; z++) {
                    char tmp[6] = {0};
                    sprintf(tmp,"%c",((unsigned char)(((unsigned char *)dst)[ z + i * rowNum])));
                    rowstr += string(tmp) + " ";
                    if (z == left - 1){
                        rowstr += "\r\n";
                    }
                }
            }
        }else{
            for (int z = 0;z < rowNum; z++) {
                char tmp[6] = {0};
                sprintf(tmp,"%02x",((unsigned char)(((unsigned char *)dst)[ z + i * rowNum])));
                rowstr += string(tmp) + " ";
                if (!ifAsii){
                    if (z == rowNum - 1){
                        rowstr += "\r\n";
                    }
                }
            }
            if(ifAsii){
                rowstr += " ";
                for (int z = 0;z < rowNum; z++) {
                    char tmp[6] = {0};
                    sprintf(tmp,"%c",((unsigned char)(((unsigned char *)dst)[ z + i * rowNum])));
                    rowstr += string(tmp) + "   ";
                    if (z == rowNum - 1){
                        rowstr += "\r\n";
                    }
                }
            }
        }
        strcat(out,rowstr.c_str());
    }
    cout << out << "\r\n";
    return  0;
}